package me.itsoo.artemis.framework.ioc.context;

import me.itsoo.artemis.framework.core.eventbus.Event;
import me.itsoo.artemis.framework.core.eventbus.EventBus;
import me.itsoo.artemis.framework.core.eventbus.Subscriber;
import me.itsoo.artemis.framework.ioc.context.event.ApplicationEvent;
import me.itsoo.artemis.framework.ioc.exception.NoSuchBeanException;
import me.itsoo.artemis.framework.ioc.factory.CacheableBeanFactory;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * AbstractApplicationContext
 *
 * @author zxy
 * @version 0.0.1
 * @since 2023/6/6
 */
public abstract class AbstractApplicationContext implements ApplicationContext {

    /**
     * 默认应用事件名称
     */
    private static final String APPLICATION_EVENT_NAME = "ApplicationEvent";

    /**
     * 全局事件发布总线缓存
     */
    private static final Map<String, EventBus> EVENT_BUS_CACHE = new ConcurrentHashMap<>();

    /**
     * 获取 BeanFactory
     *
     * @return CacheableBeanFactory
     */
    protected abstract CacheableBeanFactory getBeanFactory();

    @Override
    public Object getBean(String beanName) throws NoSuchBeanException {
        return getBeanFactory().getBean(beanName);
    }

    @Override
    public <T> T getBean(Class<T> beanClass) throws NoSuchBeanException {
        return getBeanFactory().getBean(beanClass);
    }

    @Override
    public boolean containsBean(String beanName) {
        return getBeanFactory().containsBean(beanName);
    }

    @Override
    public EventBus getApplicationEventBus() {
        return EVENT_BUS_CACHE.computeIfAbsent(getName(), k -> EventBus.create());
    }

    @Override
    @SuppressWarnings("rawtypes")
    public void registerSubscribers(List<Class<? extends Subscriber>> subClasses) {
        getApplicationEventBus().registerAll(subClasses);
    }

    @Override
    public void publishEvent(ApplicationEvent event) {
        getApplicationEventBus().publishEvent(APPLICATION_EVENT_NAME, new Event<>(event));
    }
}
